package com.douban.app.service.impl;

import com.douban.app.model.Song;
import com.douban.app.param.SongQueryParam;
import com.douban.app.service.SongService;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongSupplier;

@Service
public class SongServiceImpl implements SongService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private SongService songService;

    @Override
    public Song add(Song song) {

        if (song == null) {
            return null;
        }

        if (song.getGmtCreated() == null) {
            song.setGmtCreated(LocalDateTime.now());
        }
        if (song.getGmtModified() == null) {
            song.setGmtModified(LocalDateTime.now());
        }

        return mongoTemplate.insert(song);
    }

    @Override
    public Song get(String songId) {
        if (!StringUtils.hasText(songId)){
            return null;
        }
        return mongoTemplate.findById(songId,Song.class);
    }

    @Override
    public Page<Song> list(SongQueryParam songQueryParam) {
        if (songQueryParam==null){
            SongQueryParam songParam = new SongQueryParam();
            songParam.setPageNum(1);
            songParam.setPageSize(1);
            Page<Song> songs = songService.list(songParam);
            return songs;
        }
        Criteria criteria = new Criteria();
        List<Criteria> subCris = new ArrayList();
        if (StringUtils.hasText(songQueryParam.getName())){
            subCris.add(Criteria.where("name").is(songQueryParam.getName()));
        }
        if (StringUtils.hasText(songQueryParam.getLyrics())){
            subCris.add(Criteria.where("lyrics").is(songQueryParam.getLyrics()));
        }
        if (!subCris.isEmpty()) {
            criteria.andOperator(subCris.toArray(new Criteria[]{}));
        }

        Query query = new Query(criteria);

        long count = mongoTemplate.count(query,Song.class);

        Pageable pageable = PageRequest.of(songQueryParam.getPageNum(), songQueryParam.getPageSize());
        query.with(pageable);
        List<Song> songs = mongoTemplate.find(query,Song.class);

        Page<Song> page = PageableExecutionUtils.getPage(songs, pageable, new LongSupplier() {
            @Override
            public long getAsLong() {
                return count;
            }
        });

        return page;
    }

    @Override
    public boolean modify(Song song) {
        if (song==null){
            return false;
        }
        Query query = new Query(Criteria.where("id").is(song.getId()));
        Update update = new Update();
        if (song.getLyrics()!=null){
            update.set("lyrics",song.getLyrics());
        }
        if (song.getName()!=null){
            update.set("name",song.getName());
        }
        if (song.getSingerIds()!=null){
            update.set("singerids",song.getSingerIds());
        }
        if (song.getCover()!=null){
            update.set("cover",song.getCover());
        }
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Song.class);
        return updateResult!=null&&updateResult.getModifiedCount()>0;
    }

    @Override
    public boolean delete(String songId) {
        if (!StringUtils.hasText(songId)){
            return false;
        }
        DeleteResult remove = mongoTemplate.remove(songService.get(songId));
        return remove!=null&&remove.getDeletedCount()>0;
    }

    @Override
    public List<Song> all() {
        return mongoTemplate.findAll(Song.class);
    }

    @Override
    public List<Song> getSongByName(String name) {
        Query query = new Query(Criteria.where("name").is(name));
        List<Song> songs = mongoTemplate.find(query, Song.class);
        return songs;
    }

}
